/*==============================================================================
**                                  LINDBOARD
**                      Proprietary - Copyright (C) 2014
**                      www.facebook.com/lindboard
**------------------------------------------------------------------------------
** Supported MCUs      : MCU STM32F10x
** Supported Compilers : KeilC
**------------------------------------------------------------------------------
** File name         : COM.c
**  
** Module name       : Communications Interface
**
** Summary: Source file of COm driver
**
**= History ===================================================================
** 00.00.01  14/1/2014  Cuong Chu - manhcuong.k08@gmail.com
**            - Creation
** 00.00.02  1/4/2014 Cuong Chu
**           Remove DataReceivedHandle != NULL_PTR in Init function
**           Enable RCC clock
**           Enable Pin RCC clock
**           add feature enable/disable interrupt receive handle
** 00.00.03  28/07/2014 Cuong Chu
**           Added COM4,COM5 
** 00.00.04  06/08/2014 Cuong Chu
**           Added USART2 remap option
==============================================================================*/
/******************************************************************************/
/* INCLUSIONS                                                                 */
/******************************************************************************/
#include "COM/COM.h"
#include "stm32f10x.h"
#include "misc/misc.h"
#include "comm/comm_cfg.h"
/*******************************************************************************/
/* GLOBAL CONFIGURATIONS                                                       */
/*******************************************************************************/
/* configuration hardware parameter */
extern const ComM_PortConfigType ComM_PortConfig[COMM_NBR_COM];
/******************************************************************************/
/* DEFINITION OF LOCAL VARIABLE                                               */
/******************************************************************************/
static void (*DataReceivedHandler[COMM_NBR_COM])(uint8_t);
/* baudrate values */
static const uint32_t ComBaudrate[] =
{
  9600,
  19200,
  38400,
  57600,
  115200
};
/* hardware COM */
static USART_TypeDef*       COMx[]                = {USART1,USART2,USART3,UART4,UART5};
static const uint8_t        USART_RCC_Config[]    = {14,17,18,19,20};
static const uint8_t        PORT_RCC_Cfg[]        = 
                                                    {
#if(COM_USART1_REMAP == STD_ON)                                                    
                                                      3,
#else
                                                      2,
#endif /* COM_USART1_REMAP == STD_ON */
#if(COM_USART2_REMAP == STD_ON)
                                                      5,
#else
                                                      2,
#endif/* COM_USART2_REMAP == STD_ON */
                                                      3,
                                                      4,
                                                      5
                                                    };
static GPIO_TypeDef*        PinPort[]             = 
                                                    {
#if(COM_USART1_REMAP == STD_ON)                                                    
                                                      GPIOB,
#else
                                                      GPIOA,
#endif /* COM_USART1_REMAP == STD_ON */                                                      
#if(COM_USART2_REMAP == STD_ON)
                                                      GPIOD,
#else
                                                      GPIOA,
#endif/* COM_USART2_REMAP == STD_ON */
                                                      GPIOB,
                                                      GPIOC,
                                                      GPIOC
                                                    }; 
static GPIO_TypeDef*        PinPort1[]            = 
                                                    {
#if(COM_USART1_REMAP == STD_ON)                                                    
                                                      GPIOB,
#else
                                                      GPIOA,
#endif /* COM_USART1_REMAP == STD_ON */  
#if(COM_USART2_REMAP == STD_ON)
                                                      GPIOD,
#else /* COM_USART2_REMAP == STD_ON */
                                                      GPIOA,
#endif
                                                      GPIOB,
                                                      GPIOC,
                                                      GPIOD
                                                    }; 
static const uint8_t        TxPin_Idx[]           = 
                                                    {
/* USART1 */                                                    
#if(COM_USART1_REMAP == STD_ON)
                                                      6,
#else
                                                      9,
#endif /* (COM_USART1_REMAP == STD_ON) */
/* USART2 */
#if(COM_USART2_REMAP == STD_ON)
                                                      5,
#else
                                                      2,
#endif /* (COM_USART2_REMAP == STD_ON) */
/* USART3 */
                                                      10,
/* UART4 */                                                      
                                                      10,
/* UART5 */                                                      
                                                      12
                                                    };
static const uint8_t        RxPin_Idx[]           = 
                                                    {
/* USART1 */
#if(COM_USART1_REMAP == STD_ON)
                                                      7,
#else
                                                      10,
#endif /* (COM_USART1_REMAP == STD_ON) */
/* USART2 */
#if(COM_USART2_REMAP == STD_ON)
                                                      6,
#else
                                                      3,
#endif
/* USART3 */
                                                      11,
/* UART4 */                                                      
                                                      11,
/* UART5 */                                                      
                                                      2
                                                    };
/* ahpb prescaler */
static __I uint8_t          APBAHBPrescTable[16]  = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};
static __I uint8_t          ADCPrescTable[4]      = {2, 4, 6, 8};
typedef struct
{
  uint32_t SYSCLK_Frequency; /*  SYSCLK clock frequency expressed in Hz */
  uint32_t HCLK_Frequency;   /*  HCLK clock frequency expressed in Hz */
  uint32_t PCLK1_Frequency;  /*  PCLK1 clock frequency expressed in Hz */
  uint32_t PCLK2_Frequency;  /*  PCLK2 clock frequency expressed in Hz */
	uint32_t ADCCLK_Frequency; /*  returns ADCCLK clock frequency expressed in Hz */
}RCC_ClocksTypeDef;
/******************************************************************************/
/* DEFINITION OF CONSTANTS                                                    */
/******************************************************************************/
#define NULL_PTR ((void *)0)
#define CFGR_PLLMull_Mask         ((uint32_t)0x003C0000)
#define CFGR_PLLSRC_Mask          ((uint32_t)0x00010000)
#define CFGR_PLLXTPRE_Mask        ((uint32_t)0x00020000)
#define CFGR_SWS_Mask             ((uint32_t)0x0000000C)
#define CFGR_SW_Mask              ((uint32_t)0xFFFFFFFC)
#define CFGR_HPRE_Reset_Mask      ((uint32_t)0xFFFFFF0F)
#define CFGR_HPRE_Set_Mask        ((uint32_t)0x000000F0)
#define CFGR_PPRE1_Reset_Mask     ((uint32_t)0xFFFFF8FF)
#define CFGR_PPRE1_Set_Mask       ((uint32_t)0x00000700)
#define CFGR_PPRE2_Reset_Mask     ((uint32_t)0xFFFFC7FF)
#define CFGR_PPRE2_Set_Mask       ((uint32_t)0x00003800)
#define CFGR_ADCPRE_Reset_Mask    ((uint32_t)0xFFFF3FFF)
#define CFGR_ADCPRE_Set_Mask      ((uint32_t)0x0000C000)
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL) 
/* CFGR2 register bit mask */
 #define CFGR2_PREDIV1SRC         ((uint32_t)0x00010000)
 #define CFGR2_PREDIV1            ((uint32_t)0x0000000F)
#endif
/******************************************************************************/
/* DEFINITION OF INTERNAL FUNCTIONS                                           */
/******************************************************************************/
/*******************************************************************************
** Function name: DV_COM_RCCGetClocksFreq( RCC_ClocksTypeDef* RCC_Clocks )
** Description  : This function can be used by the user application to compute  
**                the baudrate for the communication peripherals or configure 
**                other parameters.
** Parameter    : RCC_Clocks - point to struct
** Return value : None 
** Remarks      : global variables used, side effects
*******************************************************************************/
static __INLINE void DV_COM_RCCGetClocksFreq
(
  RCC_ClocksTypeDef* RCC_Clocks
);
/******************************************************************************/
/* DEFINITION OF GLOBAL FUNCTIONS                                             */
/******************************************************************************/
/*******************************************************************************
** Function name: DV_COM_Init( DV_COM_NameType ComName, DV_COM_ReturnType Baud
**                             void * DataReceivedHandle )
** Description  : The function shall be init hardware communication layer
** Parameter    : ComName - Name of COM
**                Baud    - Baudrate select ( see in DV_COM_ReturnType)
**                DataReceivedHandle - point to function process interrupt when
**                                      hardware received one byte data.
** Return value : DV_COM_OK     - Process success
**                DV_COM_FAILED - Process failed
** Remarks      : global variables used, side effects
*******************************************************************************/
DV_COM_ReturnType DV_COM_Init
(
	DV_COM_NameType ComName, 
  DV_COM_BaudrateType Baud,
  void (*DataReceivedHandle)(uint8_t)
)
{
  uint32_t          tmpreg              = 0x00;
  uint32_t          apbclock            = 0x00;
  uint32_t          integerdivider      = 0x00;
  uint32_t          fractionaldivider   = 0x00;
  DV_COM_ReturnType retVal              = DV_COM_FAILED;
  RCC_ClocksTypeDef RCC_ClocksStatus;
  /* check COM is available */
  if( ComName <= COM5 )
  {


    /* RCC config for MCU peripheral USART */
    RCC->APB2ENR |= 1UL << PORT_RCC_Cfg[ComName];
    /* enable AFIO */
    RCC->APB2ENR |= 1UL ;
    if (ComName == COM1)
    {
      RCC->APB2ENR |= 1UL << USART_RCC_Config[ComName];
    }
    else
    {
      RCC->APB1ENR |= 1UL << USART_RCC_Config[ComName];	
    }
    
    switch(ComName)
    {
      case COM1:
#if (COM_USART1_REMAP == STD_ON)
        AFIO->MAPR |= (1UL<<2);
#endif       
      break;
      case COM2:
#if (COM_USART2_REMAP == STD_ON)
        AFIO->MAPR |= (1UL<<3);
#endif        
      break;
      case COM3:
      
      break;
      case COM4:
      
      break;
      case COM5:
      
      break;
    }
    /* RX pin clock */
     /* check pin select at low or high register */
    if(RxPin_Idx[ComName]<8)
    {
      if(ComName != COM5)
      {
        /* set pin mode floating input */
        PinPort[ComName]->CRL   &= ~(3UL << RxPin_Idx[ComName]*4);
        PinPort[ComName]->CRL   &= ~(3UL << (RxPin_Idx[ComName]*4+2));
        PinPort[ComName]->CRL   |= 2UL << (RxPin_Idx[ComName]*4+2);
      }
      else
      {
        /* set pin mode floating input */
        PinPort1[ComName]->CRL   &= ~(3UL << RxPin_Idx[ComName]*4);
        PinPort1[ComName]->CRL   &= ~(3UL << (RxPin_Idx[ComName]*4+2));
        PinPort1[ComName]->CRL   |= 2UL << (RxPin_Idx[ComName]*4+2);
      }
    }
    else
    {
        /* set pin mode floating input */
        PinPort[ComName]->CRH   &= ~(3UL << (RxPin_Idx[ComName]-8)*4);
        PinPort[ComName]->CRH   &= ~(3UL << ((RxPin_Idx[ComName]-8)*4+2));
        PinPort[ComName]->CRH   |= 2UL << ((RxPin_Idx[ComName]-8)*4+2);  
    }
    /* TX pin clock */
     /* check pin location */
    if(TxPin_Idx[ComName] < 8 )
    {
      /* config port output push pull */
      PinPort[ComName]->CRL  &= ~(3UL << (TxPin_Idx[ComName]*4+2));
      PinPort[ComName]->CRL  |= 2UL << (TxPin_Idx[ComName]*4+2);
      /* mode speed 50MHZ */
      PinPort[ComName]->CRL   |= 3UL << TxPin_Idx[ComName]*4;
    }
    else
    {
      /* config port output push pull */
      PinPort[ComName]->CRH   &= ~(3UL << ((TxPin_Idx[ComName]-8)*4+2 ));
      PinPort[ComName]->CRH   |= 2UL << ((TxPin_Idx[ComName]-8)*4+2);
      /* mode speed 50MHZ */
      PinPort[ComName]->CRH   |= 3UL << (TxPin_Idx[ComName]-8)*4;
    }
    /* set function pointer */
    DataReceivedHandler[ComName] = DataReceivedHandle;
    /*---------------------------- USART CR2 Configuration -----------------------*/
    /* Stop bits: 1 bit[13:12] */
    /* clear bits 13,12 */
    COMx[ComName]->CR2 &= ~(3UL << 12);
    /* select stop bits mode */
    COMx[ComName]->CR2 |= (0UL << 12);
    /*---------------------------- USART CR1 Configuration -----------------------*/
    /*  1 Start bit, 8 Data bits, n Stop bit */
    COMx[ComName]->CR1 &= ~(1UL << 12);
    COMx[ComName]->CR1 |= (0UL << 12);
    /* no parity selection */
    COMx[ComName]->CR1 &= ~(1UL << 9);
    COMx[ComName]->CR1 |= (0UL << 9);
    /* enable trasmitter & receiver */
    COMx[ComName]->CR1 |= (1UL << 3);
    COMx[ComName]->CR1 |= (1UL << 2);
    /*---------------------------- USART CR3 Configuration -----------------------*/
    /* disable hardware flow control */
    COMx[ComName]->CR2 |= (0UL);
    /*---------------------------- USART BRR Configuration -----------------------*/
    /* Configure the USART Baud Rate */
    DV_COM_RCCGetClocksFreq(&RCC_ClocksStatus);

    if (COMx[ComName] == USART1)
    {
      apbclock = RCC_ClocksStatus.PCLK2_Frequency;
    }
    else
    {
      apbclock = RCC_ClocksStatus.PCLK1_Frequency;
    }
    
    /* Determine the integer part */
    if ((COMx[ComName]->CR1 & USART_CR1_OVER8) != 0)
    {
      /* Integer part computing in case Oversampling mode is 8 Samples */
      integerdivider = ((25 * apbclock) / (2 * (ComBaudrate[Baud])));    
    }
    else /* if ((COMx[ComName]->CR1 & USART_CR1_OVER8) == 0) */
    {
      /* Integer part computing in case Oversampling mode is 16 Samples */
      integerdivider = ((25 * apbclock) / (4 * (ComBaudrate[Baud])));    
    }
    tmpreg = (integerdivider / 100) << 4;

    /* Determine the fractional part */
    fractionaldivider = integerdivider - (100 * (tmpreg >> 4));

    /* Implement the fractional part in the register */
    if ((COMx[ComName]->CR1 & USART_CR1_OVER8) != 0)
    {
      tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07);
    }
    else /* if ((COMx[ComName]->CR1 & USART_CR1_OVER8) == 0) */
    {
      tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F);
    }
    
    /* Write to USART BRR register */
    COMx[ComName]->BRR = (uint16_t)tmpreg;
    
    /* enable usart */
    COMx[ComName]->CR1 |= (1UL << 13);
    /* process success */
    retVal = DV_COM_OK;
  }
  else
  {
    /* do nothing */
  }
  return retVal;
}
/*******************************************************************************
** Function name: DV_COM_WriteByte( DV_COM_NameType ComName ,uint8_t byte )
** Description  : The function sends one byte to hardware layer
** Parameter    : ComName - COM select
**                byte - data send
** Return value : DV_COM_OK     - Process success
**                DV_COM_FAILED - Process failed
** Remarks      : global variables used, side effects
*******************************************************************************/
DV_COM_ReturnType DV_COM_WriteByte
(
  DV_COM_NameType ComName,
	uint8_t byte
)
{
  /* Transmit Data */
  COMx[ComName]->DR = (byte & (uint16_t)0x01FF);
  /* wait transmit success */
  while(  (COMx[ComName]->SR & 0x0040) == (uint16_t)0);
  return DV_COM_OK;
}
/*******************************************************************************
** Function name: DV_COM_ReadByte( DV_COM_NameType ComName )
** Description  : The function reads one byte from hardware layer
** Parameter    : ComName - COM select
** Return value : return data read from hardware
** Remarks      : global variables used, side effects
*******************************************************************************/
uint8_t DV_COM_ReadByte
(
  DV_COM_NameType ComName
)
{
  /* Reaceive Data */
  return (uint8_t)(COMx[ComName]->DR & (uint16_t)0x01FF);
}
/*******************************************************************************
** Function name: USART1_IRQHandler( void )
** Description  : Interrupt function of COM1
** Parameter    : None
** Return value : None
** Remarks      : global variables used, side effects
*******************************************************************************/
void USART1_IRQHandler
(
	void
)
{
	uint8_t c = 0xFF;
  /* check  */
  if(DataReceivedHandler[COM1] != NULL_PTR)
  {
    /* read data */
    c = DV_COM_ReadByte(COM1);
    /* call back function to trasnfer data to upper ComM module */
#if (COM_USART1_LB_DBG == STD_ON)
    DV_COM_WriteByte(COM1,c);
#endif       
    (*DataReceivedHandler[COM1])(c);
  }
  else
  {
    /* do nothing */
  } 
}
/*******************************************************************************
** Function name: USART2_IRQHandler( void )
** Description  : Interrupt function of COM2
** Parameter    : None
** Return value : None
** Remarks      : global variables used, side effects
*******************************************************************************/
void USART2_IRQHandler
(
	void
)
{
	uint8_t c = 0xFF;
  /* check  */
  if(DataReceivedHandler[COM2] != NULL_PTR)
  {
    /* read data */
    c = DV_COM_ReadByte(COM2);
    /* call back function to trasnfer data to upper ComM module */
#if (COM_USART2_LB_DBG == STD_ON)
    DV_COM_WriteByte(COM2,c);
#endif       
    (*DataReceivedHandler[COM2])(c);
  }
  else
  {
    /* do nothing */
  } 
}
/*******************************************************************************
** Function name: USART3_IRQHandler( void )
** Description  : Interrupt function of COM3
** Parameter    : None
** Return value : None
** Remarks      : global variables used, side effects
*******************************************************************************/
void USART3_IRQHandler
(
	void
)
{
	uint8_t c = 0xFF;
  /* check  */
  if(DataReceivedHandler[COM3] != NULL_PTR)
  {
    /* read data */
    c = DV_COM_ReadByte(COM3);
    /* call back function to trasnfer data to upper ComM module */
#if (COM_USART3_LB_DBG == STD_ON)
    DV_COM_WriteByte(COM3,c);
#endif       
    (*DataReceivedHandler[COM3])(c);
  }
  else
  {
    /* do nothing */
  } 
}
/*******************************************************************************
** Function name: UART5_IRQHandler( void )
** Description  : Interrupt function of COM4
** Parameter    : None
** Return value : None
** Remarks      : global variables used, side effects
*******************************************************************************/
void UART4_IRQHandler
(
	void
)
{
	uint8_t c = 0xFF;
  /* check  */
  if(DataReceivedHandler[COM4] != NULL_PTR)
  {
    /* read data */
    c = DV_COM_ReadByte(COM4);
    /* call back function to trasnfer data to upper ComM module */
    (*DataReceivedHandler[COM4])(c);
#if (COM_USART4_LB_DBG == STD_ON)
    DV_COM_WriteByte(COM4,c);
#endif       
  }
  else
  {
    /* do nothing */
  } 
}
/*******************************************************************************
** Function name: UART5_IRQHandler( void )
** Description  : Interrupt function of COM5
** Parameter    : None
** Return value : None
** Remarks      : global variables used, side effects
*******************************************************************************/
void UART5_IRQHandler
(
	void
)
{
	uint8_t c = 0xFF;
  /* check  */
  if(DataReceivedHandler[COM5] != NULL_PTR)
  {
    /* read data */
    c = DV_COM_ReadByte(COM5);
    /* call back function to trasnfer data to upper ComM module */
#if (COM_USART5_LB_DBG == STD_ON)
    DV_COM_WriteByte(COM5,c);
#endif    
    (*DataReceivedHandler[COM5])(c);
  }
  else
  {
    /* do nothing */
  } 
}
/*******************************************************************************
** Function name: DV_COM_RCCGetClocksFreq( RCC_ClocksTypeDef* RCC_Clocks )
** Description  : This function can be used by the user application to compute  
**                the baudrate for the communication peripherals or configure 
**                other parameters.
** Parameter    : RCC_Clocks - point to struct
** Return value : None 
** Remarks      : global variables used, side effects
*******************************************************************************/
static __INLINE void DV_COM_RCCGetClocksFreq
(
  RCC_ClocksTypeDef* RCC_Clocks
)
{
#ifdef STM32F40X	
  uint32_t tmp = 0, presc = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
  /* Get SYSCLK source -------------------------------------------------------*/
  tmp = RCC->CFGR & RCC_CFGR_SWS;
  switch (tmp)
  {
    case 0x00:  /* HSI used as system clock source */
      RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;
      break;
    case 0x04:  /* HSE used as system clock  source */
      RCC_Clocks->SYSCLK_Frequency = HSE_VALUE;
      break;
    case 0x08:  /* PLL used as system clock  source */

      /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN
         SYSCLK = PLL_VCO / PLLP
         */    
      pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
      pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
      
      if (pllsource != 0)
      {
        /* HSE used as PLL clock source */
        pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
      }
      else
      {
        /* HSI used as PLL clock source */
        pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);      
      }

      pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
      RCC_Clocks->SYSCLK_Frequency = pllvco/pllp;
      break;
    default:
      RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;
      break;
  }
  /* Compute HCLK, PCLK1 and PCLK2 clocks frequencies ------------------------*/
  /* Get HCLK prescaler */
  tmp = RCC->CFGR & RCC_CFGR_HPRE;
  tmp = tmp >> 4;
  presc = APBAHBPrescTable[tmp];
  /* HCLK clock frequency */
  RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc;

  /* Get PCLK1 prescaler */
  tmp = RCC->CFGR & RCC_CFGR_PPRE1;
  tmp = tmp >> 10;
  presc = APBAHBPrescTable[tmp];
  /* PCLK1 clock frequency */
  RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc;

  /* Get PCLK2 prescaler */
  tmp = RCC->CFGR & RCC_CFGR_PPRE2;
  tmp = tmp >> 13;
  presc = APBAHBPrescTable[tmp];
  /* PCLK2 clock frequency */
  RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
#endif

#ifdef STM32F10X
  uint32_t tmp = 0, pllmull = 0, pllsource = 0, presc = 0;

#ifdef  STM32F10X_CL
  uint32_t prediv1source = 0, prediv1factor = 0, prediv2factor = 0, pll2mull = 0;
#endif /* STM32F10X_CL */

#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
  uint32_t prediv1factor = 0;
#endif
    
  /* Get SYSCLK source -------------------------------------------------------*/
  tmp = RCC->CFGR & CFGR_SWS_Mask;
  
  switch (tmp)
  {
    case 0x00:  /* HSI used as system clock */
      RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;
      break;
    case 0x04:  /* HSE used as system clock */
      RCC_Clocks->SYSCLK_Frequency = HSE_VALUE;
      break;
    case 0x08:  /* PLL used as system clock */

      /* Get PLL clock source and multiplication factor ----------------------*/
      pllmull = RCC->CFGR & CFGR_PLLMull_Mask;
      pllsource = RCC->CFGR & CFGR_PLLSRC_Mask;
      
#ifndef STM32F10X_CL      
      pllmull = ( pllmull >> 18) + 2;
      
      if (pllsource == 0x00)
      {/* HSI oscillator clock divided by 2 selected as PLL clock entry */
        RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull;
      }
      else
      {
 #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
       prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1;
       /* HSE oscillator clock selected as PREDIV1 clock entry */
       RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE / prediv1factor) * pllmull; 
 #else
        /* HSE selected as PLL clock entry */
        if ((RCC->CFGR & CFGR_PLLXTPRE_Mask) != (uint32_t)RESET)
        {/* HSE oscillator clock divided by 2 */
          RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE >> 1) * pllmull;
        }
        else
        {
          RCC_Clocks->SYSCLK_Frequency = HSE_VALUE * pllmull;
        }
 #endif
      }
#else
      pllmull = pllmull >> 18;
      
      if (pllmull != 0x0D)
      {
         pllmull += 2;
      }
      else
      { /* PLL multiplication factor = PLL input clock * 6.5 */
        pllmull = 13 / 2; 
      }
            
      if (pllsource == 0x00)
      {/* HSI oscillator clock divided by 2 selected as PLL clock entry */
        RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull;
      }
      else
      {/* PREDIV1 selected as PLL clock entry */
        
        /* Get PREDIV1 clock source and division factor */
        prediv1source = RCC->CFGR2 & CFGR2_PREDIV1SRC;
        prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1;
        
        if (prediv1source == 0)
        { /* HSE oscillator clock selected as PREDIV1 clock entry */
          RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE / prediv1factor) * pllmull;          
        }
        else
        {/* PLL2 clock selected as PREDIV1 clock entry */
          
          /* Get PREDIV2 division factor and PLL2 multiplication factor */
          prediv2factor = ((RCC->CFGR2 & CFGR2_PREDIV2) >> 4) + 1;
          pll2mull = ((RCC->CFGR2 & CFGR2_PLL2MUL) >> 8 ) + 2; 
          RCC_Clocks->SYSCLK_Frequency = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull;                         
        }
      }
#endif /* STM32F10X_CL */ 
      break;

    default:
      RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;
      break;
  }

  /* Compute HCLK, PCLK1, PCLK2 and ADCCLK clocks frequencies ----------------*/
  /* Get HCLK prescaler */
  tmp = RCC->CFGR & CFGR_HPRE_Set_Mask;
  tmp = tmp >> 4;
  presc = APBAHBPrescTable[tmp];
  /* HCLK clock frequency */
  RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc;
  /* Get PCLK1 prescaler */
  tmp = RCC->CFGR & CFGR_PPRE1_Set_Mask;
  tmp = tmp >> 8;
  presc = APBAHBPrescTable[tmp];
  /* PCLK1 clock frequency */
  RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
  /* Get PCLK2 prescaler */
  tmp = RCC->CFGR & CFGR_PPRE2_Set_Mask;
  tmp = tmp >> 11;
  presc = APBAHBPrescTable[tmp];
  /* PCLK2 clock frequency */
  RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
  /* Get ADCCLK prescaler */
  tmp = RCC->CFGR & CFGR_ADCPRE_Set_Mask;
  tmp = tmp >> 14;
  presc = ADCPrescTable[tmp];
  /* ADCCLK clock frequency */
  RCC_Clocks->ADCCLK_Frequency = RCC_Clocks->PCLK2_Frequency / presc;	
#endif
}
/*******************************************************************************
** Function name: DV_COM_HardwareInterruptEnabled( DV_COM_NameType ComName )
** Description  : The function enables hardware interrupt
** Parameter    : ComName - COM select
** Return value : None
** Remarks      : global variables used, side effects
*******************************************************************************/
void DV_COM_HardwareInterruptEnabled
(
  DV_COM_NameType ComName
)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
  SCB->AIRCR = 0x05FA0000 | 0x700;
  COMx[ComName]->CR1 |= (1UL << 5);
  /* enable interrupt channel */
	NVIC_InitStructure.NVIC_IRQChannel =  ComM_PortConfig[ComName].IntChn;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = ComM_PortConfig[ComName].Prio;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init( &NVIC_InitStructure );
}
/*******************************************************************************
** Function name: DV_COM_HardwareInterruptDisabled( DV_COM_NameType ComName )
** Description  : The function disables hardware interrupt
** Parameter    : ComName - COM select
** Return value : None
** Remarks      : global variables used, side effects
*******************************************************************************/
void DV_COM_HardwareInterruptDisabled
(
  DV_COM_NameType ComName
)
{
  /* usart interrupt disable */
  COMx[ComName]->CR1 &= ~(1UL << 5);
}
/*****************************************************************************/
/* End Of File Copyright LINDBOARD 2014                                      */
/*****************************************************************************/
